<template>
    <ElRow style="width:100%;height:100%;">
        <ElCol :span="4" style="  border-right: 1px solid #ddd;">
            <div style="display:flex;align-items:center;margin-bottom:15px;">
                <ElButton size="small" type="primary" @click="toRun" :disabled="isRun">运行</ElButton>
                <ElButton size="small" @click="toStop" :disabled="!isRun">尝试停止运行</ElButton>
            </div>
            <div style="margin-bottom:10px;width:100%;overflow: hidden;text-overflow: ellipsis;
    white-space: nowrap;">
                <span :title="flowName"
                      style="margin-right:5px; font-weight: bold;cursor: pointer;">{{ '流程名称：' + flowName }}</span>
            </div>
            <div v-for="item in logStatus">
                <div>
                    <div class="run-name">{{ item.name }}</div>
                    <div class="run-val">{{ item.value || "无" }}</div>
                </div>
            </div>
        </ElCol>
        <ElCol :span="20">
            <div class="main-content">
                <div class="main-content-dom" id="flow-main-run">

                </div>
                <div class="main-content-log" :style="{ height: logHeight + 'px' }">
                    <div class="drag-bar"
                         @mousedown="startDrag"
                         :class="{ dragging: isDragging }">
                    </div>
                        <div class="log-title">
                            <span>日志内容</span>
                            <button @click="getNextLog">获取下一页日志</button>
                            <span class="log-clear" @click="logContent = '' ">清空日志</span>
                        </div>
                        <div class="log-content">
    <!--                       {{logContent}}-->
                            <textarea
                                v-model="logContent"
                                readonly
                                class="log-textarea"
                            ></textarea>
                        </div>
                </div>
            </div>

        </ElCol>
    </ElRow>

</template>

<script setup>

import {Graph, Shape} from "@antv/x6";

import {defineComponent, ref, onMounted, reactive, nextTick} from 'vue';
import {run, log} from "@data/api/data/dataDevelopment";
import {useRouter} from 'vue-router'

const {currentRoute} = useRouter();
console.log(currentRoute.value.query)
import {ElMessage} from 'element-plus'

import {flowServiceStore} from '@data/store/flow';
import {intServiceStore} from '@data/store/index';

const flowCount = flowServiceStore();
const intCount = intServiceStore();
import {storeToRefs} from 'pinia';

const {logDisposition, flowData} = storeToRefs(flowCount);
const {flowName, logStatus} = storeToRefs(intCount);
const isRun = ref(false);
const graphRun = ref(null);
const logContent = ref('');

defineComponent({
    name: 'run',
});
onMounted(() => {
    init(() => {
        graphRun.value.fromJSON(logDisposition.value.graphJson);
    });
})

let init = (callback) => {
    graphRun.value = new Graph({
        container: document.getElementById("flow-main-run"),
        autoResize: true,
        interacting: true,
        grid: {
            visible: false,
            size: 20, // 网格大小
            type: 'mesh',
            args: {
                color: '#e9e9e9',
                thickness: 2 // 网格线宽度/网格点大小
            }
        },
        // 滚轮缩放 MouseWheel
        mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: ['ctrl', 'meta'],
            maxScale: 3,
            minScale: 0.3
        },
        // 连线规则
        connecting: {
            // 路由类型
            // router: 'orth',
            // 圆角连接器，将起点、路由点、终点通过直线按顺序连接，并在线段连接处通过圆弧连接（倒圆角）。
            connector: {
                name: 'smooth',
            },
            anchor: 'center', // 当连接到节点时，通过 anchor 来指定被连接的节点的锚点，默认值为 center
            connectionPoint: 'anchor', // 指定连接点，默认值为 boundary
            // 是否允许连接到画布空白位置的点，默认为 true。
            allowBlank: false,
            allowLoop: false,
            // 距离节点或者连接桩 20px 时会触发自动吸附
            snap: {
                radius: 20
            },
            // 拽出新的边
            createEdge() {
                return new Shape.Edge({
                    attrs: {
                        line: {
                            stroke: "#A2B1C3",
                            strokeWidth: 2,
                            targetMarker: 'block',
                        },
                    },
                    zIndex: 0
                })
            },
            validateConnection({targetMagnet}) {
                return !!targetMagnet
            }
        },
        // 连线高亮
        highlighting: {
            // 连线过程中，自动吸附到链接桩时被使用。
            magnetAdsorbed: {
                name: 'stroke',
                args: {
                    attrs: {
                        width: 12,
                        r: 6,
                        magnet: true,
                        stroke: '#008CFF',
                        strokeWidth: 2,
                        fill: '#0F67FF'
                    }
                }
            }
        },
        resizing: {
            minWidth: 100,
            minHeight: 30,
        },
        snapline: true,
        keyboard: {
            enabled: true,
        },
        clipboard: {
            enabled: true,
        },
        history: {
            enabled: true,
        },
    });
    if (callback) callback();
}


let currentIndex = 0; // 用于跟踪当前处理到哪个节点

const updateNodeStatus = (graph, nodes, index) => {
    if (index < nodes.length) {
        const node = graph.getCellById(nodes[index].id);
        let data = node.getData();

        // 更新节点状态为 'running'
        node.setData({
            ...data,
            status: 'running',
        });

        // 设置延迟后将状态更新为 'completed'
        setTimeout(() => {
            data = node.getData(); // 重新获取数据，确保是最新的
            node.setData({
                ...data,
                status: 'completed',
            });

            // 更新完成之后，继续处理下一个节点
            updateNodeStatus(graph, nodes, index + 1);
        }, 1000); // 延迟1秒
    }
};

const toRun = async() => {
    const nodes = graphRun.value.getNodes(); // 获取所有节点
    if (currentIndex < nodes.length) {
        updateNodeStatus(graphRun.value, nodes, currentIndex);
        currentIndex++; // 移动到下一个节点
    } else {
        console.log("所有节点均已处理完毕");
    }

    // console.log(logDisposition.value.graphJson);

    let arr = logDisposition.value.graphJson.cells.filter(item => item.shape != "edge" && item.shape != 'start-node' && item.shape != 'end-node');

    arr = arr.map(element => {
        return {
            // ...element,
            name: element.data.label,
            type: element.data.component,
            id: element.id,
            ...flowData.value[element.id]
        }
    })

    let lineArr = logDisposition.value.graphJson.cells.filter(item =>
        item.shape == "edge" &&
        logDisposition.value.graphJson.cells.find(e => e.id == item.source.cell).shape != "start-node" &&
        logDisposition.value.graphJson.cells.find(e => e.id == item.target.cell).shape != 'end-node'
    );


    let hop = [];
    lineArr.map(item => {
        hop.push({
            from: flowData.value[item.source.cell]?.name,
            to: flowData.value[item.target.cell]?.name,
            enabled: 'Y'
        })
    })
    let connection =  arr.map(item => {
        return {
            name: item.connection,
        }
    }).filter(item => item.name) // 过滤掉name为undefined/null/空的情况

    let uniqueArray = Object.values(connection.reduce((acc, cur) => {
        if (cur.name) { // 增加有效性判断
          acc[cur.name] = cur; // 如果存在相同的name，则后一个会覆盖前一个，保证了唯一性
        }
        return acc;
    }, {}));

    let obj = {
        transformation: {
            // connection:uniqueArray.length == 1 ? uniqueArray[0] : uniqueArray,
            ...(uniqueArray.length > 0 && { connection: uniqueArray.length === 1 ? uniqueArray[0] : uniqueArray }),
            order: {
                hop: arr.length == 1 ?
                    {
                        "from": arr[0].name,
                        "to": arr[1].name,
                        "enabled": "Y"
                    } : hop//transformData(arr),
            },
            step: arr
        }
    }
    // console.log(obj);

    console.log({
        antvJsonContent: JSON.stringify({
            graph: logDisposition.value.graphJson,
            data: flowData.value
        }),
        ktrJsonContent: obj,
        ktrJsonName: flowName.value,
        ...currentRoute.value.query
    })

    // // 先获取日志检查错误
    // const logRes = log({
    //   executorId: currentRoute.value.query.ktrJsonId,
    //   logLevel: 'Debug'
    // });
    // console.log(logRes);
    //
    // logContent.value = logRes.data.log;
    // console.log(logContent);
    // // 错误检查
    // if(logRes.data?.errors > 0){
    //
    //     ElMessage.error('存在未处理的错误，终止运行');
    //     return; // 终止执行
    // }

    await run({
        antvJsonContent: Base64.encode(JSON.stringify({
            graph: logDisposition.value.graphJson,
            data: flowData.value
        })),
        ktrJsonContent: Base64.encode(JSON.stringify(obj)),
        ktrJsonName: flowName.value,
        ...currentRoute.value.query
    }).then(res => {
        ElMessage.success('任务运行');
    })

    await nextTick(log({
        executorId: currentRoute.value.query.ktrJsonId,
        logLevel: 'Debug'
    }).then(res => {
        console.log(res)
        logContent.value = res.data.log;
        console.log(logContent);
        if (res.data.errors > 0) {
            ElMessage.error('执行过程异常');
        }
    }))

};


const toStop = () => {
    isRun.value = false;
}

const getNextLog = () => {
    log({
        executorId: currentRoute.value.query.ktrJsonId,
        logLevel: 'Debug'
    }).then(res => {
        console.log(res)
        logContent.value += res.data.log;
        console.log(logContent);
        if (res.data.errors > 0) {
            ElMessage.error('执行过程异常');
        }
    })
}

const logHeight = ref(250); // 初始高度

// 新增拖拽相关方法
let isDragging = ref(false);
let startY = 0;
let startHeight = 0;

const startDrag = (e) => {
    isDragging.value = true;
    startY = e.clientY;
    startHeight = logHeight.value;
    document.addEventListener('mousemove', handleDrag);
    document.addEventListener('mouseup', stopDrag);
    document.body.style.userSelect = 'none'; // 防止拖拽时选中文本
};

const handleDrag = (e) => {
    if (!isDragging.value) return;
    requestAnimationFrame(() => {
        const deltaY = e.clientY - startY;
        const newHeight = Math.min(
            Math.max(150, startHeight - deltaY),
            window.innerHeight * 0.8 // 改为视口高度的80%
        );
        if (Math.abs(newHeight - logHeight.value) > 2) { // 增加变化阈值
            logHeight.value = newHeight;
        }
    });
};

const stopDrag = () => {
    isDragging.value = false;
    document.removeEventListener('mousemove', handleDrag);
    document.removeEventListener('mouseup', stopDrag);
    document.body.style.userSelect = '';
};
</script>

<style scoped lang="scss">
.run-name {
    font-weight: bold;
    color: #333;
    margin-right: 10px;
    font-size: 14px;
    line-height: 30px;
}

.run-val {
    font-size: 14px;
    line-height: 30px;
    color: #666;
}

.main-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
    position: relative;

    .main-content-dom {
      flex: 1;
      width: 100%;
      height: 100%;
      min-height: 800px;
      background: #eee;
    }

    .main-content-log {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        //height: 150px;
        background: #fff;
        border-top: 1px solid #ddd;
        transition: height 0.2s ease; // 添加过渡效果
    }
    .drag-bar {
        height: 5px;
        width: 100%;
        cursor: row-resize;
        background: #f0f0f0;
        position: absolute;
        top: -2px;
        z-index: 1;

        &:hover,
        &.dragging {
            background: #409eff;
        }
    }
    .log-title {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px;
        background: #f5f5f5;
        border-bottom: 1px solid #ddd;
    }
    .log-clear{
        cursor: pointer;
        color: #999;
    }
    .log-content{
        padding: 10px;
        //overflow: auto;
        height: 100%;

    }
    .log-content {
        height: calc(100% - 40px); // 留出标题栏高度

        .log-textarea {
            width: 100%;
            height: 100%;
            border: none;
            resize: none;
            background: transparent;
            padding: 0 10px;
            font-family: monospace;
            white-space: pre; // 保留原始格式
            overflow: auto;

            &:focus {
              outline: none;
              box-shadow: none;
            }
        }
    }
}
</style>